package co.fitstart.mobile.entity.appointment;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.DateUtils;

import co.fitstart.entity.coach.CoachRestCalendar;
import co.fitstart.entity.course.Course;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.site.Site;

public class AppointmentPrepare {
    
    /** 需要预约的courseRound */
    private CourseRound courseRound;
    
    /** 当前选中的门店 */
    private Site currentSite;
    
    /** 当前时间 --- 小时 */
    private String currentHour;
    
    /** 当先选中的日期 */
    private Date currentDay;
    
    /** 选中的日期是否为当日 */
    private boolean today;
    
    /** 可选的日期*/
    private List<Date> daySelector;
    
    /** 可预约开始时间 */
    private String[] appointStartTime;
    
    /** 可预约结束时间 */
    private String[] appointEndTime;
    
    /**
     * 所选的日期对应的 公共容量记录
     * key dayhour字符串
     * value 已预订的公共房间数量
     */
    private Map<String, Integer> commonRoomScheduleRecords;
    
    /**
     * 所选的日期对应的 私有容量记录
     * key dayhour字符串
     * value 已预订的私有房间数量
     */
    private Map<String, Integer> roomRoomScheduleRecords;
    
    /** 所选门店总教练数 */
    private int coachAmount;
    
    /**
     * 所选日期对应的 上课教练数
     * key dayhour字符串
     * value 上课的教练数
     */
    private Map<String, Integer> scheduleAmount;
    
    /**
     * 所选日期对应的 休息教练数
     * key dayhour字符串
     * value 休息的教练数
     */
    private Map<String, Integer> restAmount;
    
    /**
     * 所选日期对应的 休息教练数
     * key dayhour字符串
     * value 休息的教练数
     */
    private Map<String, Integer> remainCoaches;
    
    /**
     * 1v1课程预约教练当天的休息时间段
     * key dayhour字符串
     * value CoachRestCalendar
     */
    private Map<String, CoachRestCalendar> coachRestCalendar;
    
    /**
     * 1v1课程预约教练当天的所上课程
     * 
     */
    private Map<String, CourseSchedule> coachCourseSchedule;
    
    /**
     * 教练当前日期在当前门店是否可预约
     */
    private boolean unavailable;
    
    /**
     * The default constructor
     * key dayhour字符串
     * value CourseSchedule
     */
    public AppointmentPrepare() {
    }
    
    /**
     * 
     * @param courseRound
     * @param site
     * @param day
     */
    public AppointmentPrepare(CourseRound courseRound, Site site, Date day) {
        
        this.courseRound = courseRound;
        this.currentHour = DateFormatUtils.format(new Date(), "HH");
        this.currentSite = site;
        this.currentDay = day == null ? new Date() : day;
        this.today = (day == null || DateUtils.isSameDay(day, new Date()));
        
        this.appointStartTime = initAppointStartTime();
        this.appointEndTime = initAppointEndTime();
        
        this.initDaySelector();
    }
    
    /**
     * generate day selector
     */
    protected void initDaySelector() {
        
        Date startDate = new Date();
        Date endDate = DateUtils.addWeeks(startDate, 2);
        
        this.daySelector = DateUtils.getIntervalDays(startDate, endDate);
    
    }
    
    /**
     * 
     * @param roomLimits
     * @param commonLimits
     * @return
     */
    public AppointmentPrepare init(Map<String, Integer> roomLimits, Map<String, Integer> commonLimits,
                                   Map<String, Integer> scheduleAmount, Map<String, Integer> restAmount,
                                   int coachAmount) {
        this.roomRoomScheduleRecords = roomLimits;
        this.commonRoomScheduleRecords = commonLimits;
        this.scheduleAmount = scheduleAmount;
        this.restAmount = restAmount;
        this.coachAmount = coachAmount;
        
        return this;
    }
    
    public AppointmentPrepare init(Map<String, Integer> roomLimits, Map<String, Integer> commonLimits,
                                   Map<String, Integer> remainCoaches) {
        this.roomRoomScheduleRecords = roomLimits;
        this.commonRoomScheduleRecords = commonLimits;
        this.remainCoaches = remainCoaches;
        
        return this;
        }
    
    /**
     * 
     * @param coachRestCalendars
     * @param coachCourseSchedules
     * @return
     */
    public AppointmentPrepare individualInit(Map<String, CoachRestCalendar> coachRestCalendars, Map<String, CourseSchedule> coachCourseSchedules) {
        this.coachRestCalendar = coachRestCalendars;
        this.coachCourseSchedule = coachCourseSchedules;
        
        return this;
    }
    
    /**
     * 
     * @return
     */
    public AppointmentPrepare unavailable() {
        this.unavailable = true;
        
        return this;
    }
    
    /**
     * 
     * @return
     */
    public String[] initAppointStartTime() {
        Course course = courseRound.getCourse();
        if(StringUtils.isEmpty(course.getAppointStartTime())) {
            return currentSite.getAppointStart();
        } else {
            Date courseAppoint = DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyy-MM-dd") + " " + course.getAppointStartTime() + ":00", "yyyy-MM-dd HH:mm:ss");
            Date siteAppoint = DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyy-MM-dd") + " " + currentSite.getAppointStartHour() + ":00", "yyyy-MM-dd HH:mm:ss");
            
            String appointStart = courseAppoint.after(siteAppoint) ? course.getAppointStartTime() : currentSite.getAppointStartHour();
            return StringUtils.split(appointStart, ":");
        }
    }
    
    /**
     * 
     * @return
     */
    public String[] initAppointEndTime() {
        String[] appointEnd;
        Course course = courseRound.getCourse();
        if(StringUtils.isEmpty(course.getAppointEndTime())) {
            appointEnd = currentSite.getAppointEnd();
        } else {
            Date courseAppoint = DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyy-MM-dd") + " " + course.getAppointEndTime() + ":00", "yyyy-MM-dd HH:mm:ss");
            Date siteAppoint = DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyy-MM-dd") + " " + currentSite.getAppointEndHour() + ":00", "yyyy-MM-dd HH:mm:ss");
            
            appointEnd = StringUtils.split(courseAppoint.before(siteAppoint) ? course.getAppointEndTime() : currentSite.getAppointEndHour(), ":");
        }
        
        if(courseRound.getCourseType().isIndividual() && course.isExperience()) {
            if("00".equals(appointEnd[1])) {
                return new String[]{Integer.toString(Integer.parseInt(appointEnd[0]) - 1), "30"};
            } else {
                return new String[]{appointEnd[0], "00"};
            }
        } else {
            return appointEnd;
        }
    }
    
    /**
     * 
     * @return
     */
    public Map<String, Object> describePrepare() {
        
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("courseRound", this.courseRound);
        result.put("currentSite", this.currentSite);
        result.put("currentHour", this.currentHour);
        result.put("currentDay", this.currentDay);
        result.put("today", this.today);
        result.put("thisWeek", this.daySelector);
        result.put("commonRecords", this.commonRoomScheduleRecords);
        result.put("roomRecords", this.roomRoomScheduleRecords);
        result.put("scheduleAmount", this.scheduleAmount);
        result.put("restAmount", this.restAmount);
        result.put("coachAmount", this.coachAmount);
        result.put("remainCoaches", this.remainCoaches);
        
        result.put("appointStartTime", this.appointStartTime);
        result.put("appointEndTime", this.appointEndTime);
        
        return result;
    }

    /**
     * 
     * @return
     */
    public Map<String, Object> describePrepareIndividual() {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("coachRestCalendars", coachRestCalendar);
        result.put("coachCourseSchedule", coachCourseSchedule);
        
        return result;
    }
    
    public Map<String, Object> describeCoachAppoint() {
        
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("courseRound", this.courseRound);
        result.put("currentSite", this.currentSite);
        result.put("currentHour", this.currentHour);
        result.put("currentDay", this.currentDay);
        result.put("today", this.today);
        result.put("thisWeek", this.daySelector);
        result.put("commonRecords", this.commonRoomScheduleRecords);
        result.put("roomRecords", this.roomRoomScheduleRecords);
        result.put("scheduleAmount", this.scheduleAmount);
        result.put("restAmount", this.restAmount);
        result.put("coachAmount", this.coachAmount);
        result.put("remainCoaches", this.remainCoaches);
        
        result.put("appointStartTime", this.appointStartTime);
        result.put("appointEndTime", this.appointEndTime);
        
        result.put("scheduleMap", this.coachCourseSchedule);
        result.put("restMap", this.coachRestCalendar);
        
        return result;
    }
    
    public Map<String, Object> describeUnavailable() {
        
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("courseRound", this.courseRound);
        result.put("currentSite", this.currentSite);
        result.put("currentHour", this.currentHour);
        result.put("currentDay", this.currentDay);
        result.put("today", this.today);
        result.put("thisWeek", this.daySelector);
        result.put("unavailable", this.unavailable);
        
        return result;
    }

    public CourseRound getCourseRound() {
        return courseRound;
    }

    public void setCourseRound(CourseRound courseRound) {
        this.courseRound = courseRound;
    }

    public Site getCurrentSite() {
        return currentSite;
    }

    public void setCurrentSite(Site currentSite) {
        this.currentSite = currentSite;
    }

    public String getCurrentHour() {
        return currentHour;
    }

    public void setCurrentHour(String currentHour) {
        this.currentHour = currentHour;
    }

    public Date getCurrentDay() {
        return currentDay;
    }

    public void setCurrentDay(Date currentDay) {
        this.currentDay = currentDay;
    }

    public boolean isToday() {
        return today;
    }

    public void setToday(boolean today) {
        this.today = today;
    }

    public List<Date> getDaySelector() {
        return daySelector;
    }

    public void setDaySelector(List<Date> daySelector) {
        this.daySelector = daySelector;
    }

    public String[] getAppointStartTime() {
        return appointStartTime;
    }

    public void setAppointStartTime(String[] appointStartTime) {
        this.appointStartTime = appointStartTime;
    }

    public String[] getAppointEndTime() {
        return appointEndTime;
    }

    public void setAppointEndTime(String[] appointEndTime) {
        this.appointEndTime = appointEndTime;
    }

    public Map<String, Integer> getCommonRoomScheduleRecords() {
        return commonRoomScheduleRecords;
    }

    public void setCommonRoomScheduleRecords(Map<String, Integer> commonRoomScheduleRecords) {
        this.commonRoomScheduleRecords = commonRoomScheduleRecords;
    }

    public Map<String, Integer> getRoomRoomScheduleRecords() {
        return roomRoomScheduleRecords;
    }

    public void setRoomRoomScheduleRecords(Map<String, Integer> roomRoomScheduleRecords) {
        this.roomRoomScheduleRecords = roomRoomScheduleRecords;
    }

    public int getCoachAmount() {
        return coachAmount;
    }

    public void setCoachAmount(int coachAmount) {
        this.coachAmount = coachAmount;
    }

    public Map<String, Integer> getScheduleAmount() {
        return scheduleAmount;
    }

    public void setScheduleAmount(Map<String, Integer> scheduleAmount) {
        this.scheduleAmount = scheduleAmount;
    }

    public Map<String, Integer> getRestAmount() {
        return restAmount;
    }

    public void setRestAmount(Map<String, Integer> restAmount) {
        this.restAmount = restAmount;
    }

    public Map<String, Integer> getRemainCoaches() {
        return remainCoaches;
    }

    public void setRemainCoaches(Map<String, Integer> remainCoaches) {
        this.remainCoaches = remainCoaches;
    }

    public Map<String, CoachRestCalendar> getCoachRestCalendar() {
        return coachRestCalendar;
    }

    public void setCoachRestCalendar(Map<String, CoachRestCalendar> coachRestCalendar) {
        this.coachRestCalendar = coachRestCalendar;
    }

    public Map<String, CourseSchedule> getCoachCourseSchedule() {
        return coachCourseSchedule;
    }

    public void setCoachCourseSchedule(Map<String, CourseSchedule> coachCourseSchedule) {
        this.coachCourseSchedule = coachCourseSchedule;
    }

    /**
     * @return the unavailable
     */
    public boolean isUnavailable() {
        return unavailable;
    }

    /**
     * @param unavailable the unavailable to set
     */
    public void setUnavailable(boolean unavailable) {
        this.unavailable = unavailable;
    }
}
